/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <iostream>

#include "restool_errors.h"

namespace OHOS {
namespace Global {
namespace Restool {
const std::map<uint32_t, ErrorInfo> ERRORS_MAP = {
    // 11200000
    { ERR_CODE_UNDEFINED_ERROR,
      { ERR_CODE_UNDEFINED_ERROR, "Undefined Error", "Unknown error: %s", "", { "Please try again." }, {} } },

    // 11201xxx
    { ERR_CODE_LOAD_LIBRARY_FAIL,
      { ERR_CODE_LOAD_LIBRARY_FAIL,
        ERR_TYPE_DEPENDENCY,
        "Failed to load the library '%s', %s",
        "",
        { "Make sure the library path is correct and has access permissions.",
          "Install the missing third-party dependency libraries displayed in the error information.",
          "Adding the path 'openharmony\\previewer\\common\\bin' in your SDK path to environment variables." },
        {} } },

    // 11203xxx
    { ERR_CODE_OPEN_JSON_FAIL,
      { ERR_CODE_OPEN_JSON_FAIL,
        ERR_TYPE_CONFIG,
        "Failed to open the JSON file '%s', %s.",
        "",
        { "Make sure the JSON file path is correct and has access permissions." },
        {} } },
    { ERR_CODE_JSON_FORMAT_ERROR,
      { ERR_CODE_JSON_FORMAT_ERROR,
        ERR_TYPE_CONFIG,
        "Failed to parse the JSON file, format is incorrect.",
        "",
        { "Check the JSON file and delete unnecessary commas (,).",
          "Check the JSON file to make sure the root bracket is {}." },
        {} } },
    { ERR_CODE_JSON_NODE_MISMATCH,
      { ERR_CODE_JSON_NODE_MISMATCH,
        ERR_TYPE_CONFIG,
        "The value type of node '%s' does not match, expected type: %s.",
        "",
        {},
        {} } },
    { ERR_CODE_JSON_NODE_MISSING,
      { ERR_CODE_JSON_NODE_MISSING, ERR_TYPE_CONFIG, "The required node '%s' is missing.", "", {}, {} } },
    { ERR_CODE_JSON_NODE_EMPTY,
      { ERR_CODE_JSON_NODE_EMPTY, ERR_TYPE_CONFIG, "The array or object node '%s' cannot be empty.", "", {}, {} } },
    { ERR_CODE_JSON_NOT_ONE_MEMBER,
      { ERR_CODE_JSON_NOT_ONE_MEMBER,
        ERR_TYPE_CONFIG,
        "The node '%s' of the JSON file can only have one member.",
        "",
        {},
        {} } },
    { ERR_CODE_JSON_INVALID_NODE_NAME,
      { ERR_CODE_JSON_INVALID_NODE_NAME,
        ERR_TYPE_CONFIG,
        "Invalid node name '%s', it should be one of %s.",
        "",
        {},
        {} } },

    // 11204xxx
    { ERR_CODE_CREATE_FILE_ERROR,
      { ERR_CODE_CREATE_FILE_ERROR,
        ERR_TYPE_FILE_RESOURCE,
        "Failed to create directory or file '%s', %s.",
        "",
        { "Make sure the file path is correct and has access permissions." },
        {} } },
    { ERR_CODE_REMOVE_FILE_ERROR,
      { ERR_CODE_REMOVE_FILE_ERROR,
        ERR_TYPE_FILE_RESOURCE,
        "Failed to delete directory or file '%s', %s.",
        "",
        { "Make sure the file path is correct and has access permissions." },
        {} } },
    { ERR_CODE_COPY_FILE_ERROR,
      { ERR_CODE_COPY_FILE_ERROR,
        ERR_TYPE_FILE_RESOURCE,
        "Failed to copy file from '%s' to '%s', %s.",
        "",
        { "Make sure the src and dest file path is correct and has access permissions." },
        {} } },
    { ERR_CODE_OPEN_FILE_ERROR,
      { ERR_CODE_OPEN_FILE_ERROR,
        ERR_TYPE_FILE_RESOURCE,
        "Failed to open file '%s', %s.",
        "",
        { "Make sure the file path is correct and has access permissions." },
        {} } },
    { ERR_CODE_READ_FILE_ERROR,
      { ERR_CODE_READ_FILE_ERROR,
        ERR_TYPE_FILE_RESOURCE,
        "Failed to read file '%s', %s.",
        "",
        { "Make sure the file content is correct." },
        {} } },

    // 11210xxx
    { ERR_CODE_UNKNOWN_COMMAND_ERROR,
      { ERR_CODE_UNKNOWN_COMMAND_ERROR,
        ERR_TYPE_COMMAND_PARSE,
        "Unknown command error: %s",
        "",
        { "For details, see the help with option -h/--help." },
        {} } },
    { ERR_CODE_UNKNOWN_OPTION,
      { ERR_CODE_UNKNOWN_OPTION,
        ERR_TYPE_COMMAND_PARSE,
        "Unknown option '%s'.",
        "",
        { "For details, see the help with option -h/--help." },
        {} } },
    { ERR_CODE_MISSING_ARGUMENT,
      { ERR_CODE_MISSING_ARGUMENT,
        ERR_TYPE_COMMAND_PARSE,
        "Option '%s' should have a argument.",
        "",
        { "For details, see the help with option -h/--help." },
        {} } },
    { ERR_CODE_INVALID_ARGUMENT,
      { ERR_CODE_INVALID_ARGUMENT,
        ERR_TYPE_COMMAND_PARSE,
        "Invalid argument value '%s'.",
        "",
        { "For details, see the help with option -h/--help." },
        {} } },
    { ERR_CODE_INVALID_INPUT,
      { ERR_CODE_INVALID_INPUT,
        ERR_TYPE_COMMAND_PARSE,
        "Invalid input path '%s'.",
        "",
        { "Make sure the input path of option -i/--inputPath is correct." },
        {} } },
    { ERR_CODE_DUPLICATE_INPUT,
      { ERR_CODE_DUPLICATE_INPUT,
        ERR_TYPE_COMMAND_PARSE,
        "Duplicated input path '%s'.",
        "",
        { "Make sure the input path of option -i/--inputPath is unique." },
        {} } },
    { ERR_CODE_DOUBLE_PACKAGE_NAME,
      { ERR_CODE_DOUBLE_PACKAGE_NAME,
        ERR_TYPE_COMMAND_PARSE,
        "The package name '%s' and '%s' conflict.",
        "",
        { "Make sure the option -p/--packageName only specified once." },
        {} } },
    { ERR_CODE_INVALID_OUTPUT,
      { ERR_CODE_INVALID_OUTPUT,
        ERR_TYPE_COMMAND_PARSE,
        "Invalid output path '%s'.",
        "",
        { "Make sure the output path of option -o/--outputPath is correct." },
        {} } },
    { ERR_CODE_DOUBLE_OUTPUT,
      { ERR_CODE_DOUBLE_OUTPUT,
        ERR_TYPE_COMMAND_PARSE,
        "The output path '%s' and '%s' conflict.",
        "",
        { "Make sure the option -o/--outputPath only specified once." },
        {} } },
    { ERR_CODE_DUPLICATE_RES_HEADER,
      { ERR_CODE_DUPLICATE_RES_HEADER,
        ERR_TYPE_COMMAND_PARSE,
        "Duplicated res header path '%s'.",
        "",
        { "Make sure the path of option -r/--resHeader is unique." },
        {} } },
    { ERR_CODE_DOUBLE_MODULES,
      { ERR_CODE_DOUBLE_MODULES,
        ERR_TYPE_COMMAND_PARSE,
        "The module name '%s' and '%s' conflict.",
        "",
        { "Make sure the option -m/--modules only specified once." },
        {} } },
    { ERR_CODE_DUPLICATE_MODULE_NAME,
      { ERR_CODE_DUPLICATE_MODULE_NAME,
        ERR_TYPE_COMMAND_PARSE,
        "Duplicated module name '%s'.",
        "",
        { "Make sure the module names specified with option -m/--modules is unique." },
        {} } },
    { ERR_CODE_DOUBLE_CONFIG_JSON,
      { ERR_CODE_DOUBLE_CONFIG_JSON,
        ERR_TYPE_COMMAND_PARSE,
        "The module.json(in Stage Model) or config.json(in FA Model) path '%s' and '%s' conflict.",
        "",
        { "Make sure the option -j/--json only specified once." },
        {} } },
    { ERR_CODE_INVALID_START_ID,
      { ERR_CODE_INVALID_START_ID,
        ERR_TYPE_COMMAND_PARSE,
        "Invalid start id '%s', out of range.",
        "",
        { "Make sure the start id in the scope [0x01000000, 0x06FFFFFF) or [0x08000000, 0xFFFFFFFF)." },
        {} } },
    { ERR_CODE_DUPLICATE_APPEND_PATH,
      { ERR_CODE_DUPLICATE_APPEND_PATH,
        ERR_TYPE_COMMAND_PARSE,
        "Duplicated append path '%s'.",
        "",
        { "Make sure the path of option -x/--append is unique." },
        {} } },
    { ERR_CODE_DOUBLE_TARGET_CONFIG,
      { ERR_CODE_DOUBLE_TARGET_CONFIG,
        ERR_TYPE_COMMAND_PARSE,
        "The target config '%s' and '%s' conflict.",
        "",
        { "Make sure the option --target-config only specified once." },
        {} } },
    { ERR_CODE_INVALID_TARGET_CONFIG,
      { ERR_CODE_INVALID_TARGET_CONFIG,
        ERR_TYPE_COMMAND_PARSE,
        "Invalid target config argument '%s'.The argument format of option --target-config is supposed to be like "
        "'Locale[zh_CN,en_US];Device[phone]'.",
        "",
        { "For more information, see the developer documentation." },
        {} } },
    { ERR_CODE_INVALID_SYSTEM_ID_DEFINED,
      { ERR_CODE_INVALID_SYSTEM_ID_DEFINED,
        ERR_TYPE_COMMAND_PARSE,
        "Invalid system id_defined.json path '%s'.",
        "",
        { "Make sure the system id_defined.json path is correct." },
        {} } },
    { ERR_CODE_DUPLICATE_SYSTEM_ID_DEFINED,
      { ERR_CODE_DUPLICATE_SYSTEM_ID_DEFINED,
        ERR_TYPE_COMMAND_PARSE,
        "Duplicated system id_defined.json path '%s'.",
        "",
        { "Make sure the system id_defined.json path is unique." },
        {} } },
    { ERR_CODE_DOUBLE_COMPRESSION_PATH,
      { ERR_CODE_DOUBLE_COMPRESSION_PATH,
        ERR_TYPE_COMMAND_PARSE,
        "The compression JSON path '%s' and '%s' conflict.",
        "",
        { "Make sure the option --compressed-config only specified once." },
        {} } },
    { ERR_CODE_NON_ASCII,
      { ERR_CODE_NON_ASCII,
        ERR_TYPE_COMMAND_PARSE,
        "The argument value '%s' is not an ASCII value.",
        "",
        { "Make sure all the arguments value characters is ASCII." },
        {} } },
    { ERR_CODE_EXCLUSIVE_OPTION,
      { ERR_CODE_EXCLUSIVE_OPTION,
        ERR_TYPE_COMMAND_PARSE,
        "Option '%s' and '%s' cannot be used together.",
        "",
        {},
        {} } },
    { ERR_CODE_PACKAGE_NAME_EMPTY,
      { ERR_CODE_PACKAGE_NAME_EMPTY,
        ERR_TYPE_COMMAND_PARSE,
        "The package name is empty, it should be specified with option -p/--packageName",
        "",
        { "Specifies the package name with option -p/--packageName." },
        {} } },
    { ERR_CODE_RES_HEADER_PATH_EMPTY,
      { ERR_CODE_RES_HEADER_PATH_EMPTY,
        ERR_TYPE_COMMAND_PARSE,
        "The resource header path(like ./ResourceTable.js, ./ResrouceTable.h) is empty, it should be specified with "
        "option -r/--resHeader.",
        "",
        { "Specifies header path with option -r/--resHeader." },
        {} } },
    { ERR_CODE_DUMP_MISSING_INPUT,
      { ERR_CODE_DUMP_MISSING_INPUT,
        ERR_TYPE_COMMAND_PARSE,
        "The HAP path of the resource dump command is missing.",
        "",
        { "Specifies a HAP path with dump command." },
        {} } },
    { ERR_CODE_DUMP_INVALID_INPUT,
      { ERR_CODE_DUMP_INVALID_INPUT,
        ERR_TYPE_COMMAND_PARSE,
        "Invalid HAP path '%s' of the resource dump command.",
        "",
        { "Make sure the HAP path of dump command is correct." },
        {} } },
    { ERR_CODE_INVALID_THREAD_COUNT,
      { ERR_CODE_INVALID_THREAD_COUNT,
        ERR_TYPE_COMMAND_PARSE,
        "Invalid thread count '%s', it should be an integer and greater than 0.",
        "",
        {},
        {} } },
    { ERR_CODE_INVALID_IGNORE_FILE,
      { ERR_CODE_INVALID_IGNORE_FILE,
        ERR_TYPE_COMMAND_PARSE,
        "Invalid ignore file pattern '%s', %s",
        "",
        { "Make sure the argument of the option --ignored-file is not empty and contains valid regular expressions." },
        {} } },

    // 11211xxx
    { ERR_CODE_OUTPUT_EXIST,
      { ERR_CODE_OUTPUT_EXIST,
        ERR_TYPE_RESOURCE_PACK,
        "Output path exists, but option -f/--forceWrite not specified.",
        "",
        { "Remove the exist output dir or use option -f to force write." },
        {} } },
    { ERR_CODE_CONFIG_JSON_MISSING,
      { ERR_CODE_CONFIG_JSON_MISSING,
        ERR_TYPE_RESOURCE_PACK,
        "Multiple input paths, but the module.json(in Stage Model) or config.json(in FA Model) path is not specified "
        "with option -j/--json.",
        "",
        { "Specifies option -j/--json." },
        {} } },
    { ERR_CODE_INVALID_MODULE_TYPE,
      { ERR_CODE_INVALID_MODULE_TYPE,
        ERR_TYPE_RESOURCE_PACK,
        "Invalid module type '%s', it should be one of [\"entry\", \"har\", \"shared\", \"feature\"].",
        "",
        {},
        {} } },
    { ERR_CODE_EXCLUSIVE_START_ID,
      { ERR_CODE_EXCLUSIVE_START_ID,
        ERR_TYPE_RESOURCE_PACK,
        "The id_defined.json and the start id '%lu' specified with option -e/--startId conflict.",
        "",
        { "Retain only one of the id_defined.json and the start id." },
        {} } },
    { ERR_CODE_ID_DEFINED_INVALID_TYPE,
      { ERR_CODE_ID_DEFINED_INVALID_TYPE,
        ERR_TYPE_RESOURCE_PACK,
        "Invalid resource type '%s' in the id_defined.json, it should be one of %s.",
        "",
        {},
        {} } },
    { ERR_CODE_ID_DEFINED_INVALID_ID,
      { ERR_CODE_ID_DEFINED_INVALID_ID,
        ERR_TYPE_RESOURCE_PACK,
        "Invalid id value '%s' in the id_defined.json, it shoud be a hex string, match the pattern "
        "^0[xX][0-9a-fA-F]{8}, and in the scope [0x01000000,0x06FFFFFF] or [0x08000000,0xFFFFFFFF].",
        "",
        {},
        {} } },
    { ERR_CODE_ID_DEFINED_ORDER_MISMATCH,
      { ERR_CODE_ID_DEFINED_ORDER_MISMATCH,
        ERR_TYPE_RESOURCE_PACK,
        "The order value '%lu' in the id_defined.json does not match the record element sequence '%lu', "
        "expected value: %lu.",
        "",
        { "Make sure the order value is same as the sequence." },
        {} } },
    { ERR_CODE_ID_DEFINED_SAME_ID,
      { ERR_CODE_ID_DEFINED_SAME_ID,
        ERR_TYPE_RESOURCE_PACK,
        "The name '%s' and '%s' in the id_defined.json define the same ID.",
        "",
        {},
        {} } },
    { ERR_CODE_MODULE_NAME_NOT_FOUND,
      { ERR_CODE_MODULE_NAME_NOT_FOUND,
        ERR_TYPE_RESOURCE_PACK,
        "The module name '%s' not found in %s, which specifies with -m/--modules.",
        "",
        { "Make sure the module name in module.json(in Stage Model) or config.json(in FA Model) is correct." },
        {} } },
    { ERR_CODE_INVALID_RESOURCE_PATH,
      { ERR_CODE_INVALID_RESOURCE_PATH,
        ERR_TYPE_RESOURCE_PACK,
        "Failed to scan resources, invalid path '%s', %s.",
        "",
        {},
        {} } },
    { ERR_CODE_INVALID_LIMIT_KEY,
      { ERR_CODE_INVALID_LIMIT_KEY,
        ERR_TYPE_RESOURCE_PACK,
        "Invalid qualifiers key '%s', it should match the pattern of qualifiers directory,for example zh_CN,en_US,etc.",
        "",
        { "For more information, see the developer documentation." },
        {} } },
    { ERR_CODE_INVALID_RESOURCE_DIR,
      { ERR_CODE_INVALID_RESOURCE_DIR,
        ERR_TYPE_RESOURCE_PACK,
        "Invalid resource directory name '%s', it should be one of %s.",
        "",
        {},
        {} } },
    { ERR_CODE_INVALID_TRANSLATE_PRIORITY,
      { ERR_CODE_INVALID_TRANSLATE_PRIORITY,
        ERR_TYPE_RESOURCE_PACK,
        "Invalid translate priority value '%s', it should be one of %s.",
        "",
        {},
        {} } },
    { ERR_CODE_INVALID_ELEMENT_TYPE,
      { ERR_CODE_INVALID_ELEMENT_TYPE,
        ERR_TYPE_RESOURCE_PACK,
        "Unsupported element resource type '%s', it should be one of %s.",
        "",
        {},
        {} } },
    { ERR_CODE_INVALID_COLOR_VALUE,
      { ERR_CODE_INVALID_COLOR_VALUE,
        ERR_TYPE_RESOURCE_PACK,
        "Invalid color value '%s' of the resource '%s', it only supported reference '$color:xxx' or '#rgb','#argb',"
        "'#rrggbb','#aarrggbb'.",
        "",
        {},
        {} } },
    { ERR_CODE_INVALID_RESOURCE_REF,
      { ERR_CODE_INVALID_RESOURCE_REF,
        ERR_TYPE_RESOURCE_PACK,
        "Invalid resource reference '%s', it only supported reference '%sxxx'.",
        "",
        {},
        {} } },
    { ERR_CODE_PARENT_EMPTY,
      { ERR_CODE_PARENT_EMPTY,
        ERR_TYPE_RESOURCE_PACK,
        "The parent value of resource '%s' is empty, it should be a valid resource name.",
        "",
        {},
        {} } },
    { ERR_CODE_ARRAY_TOO_LARGE,
      { ERR_CODE_ARRAY_TOO_LARGE,
        ERR_TYPE_RESOURCE_PACK,
        "The array resource '%s' is to large, the total length of the value of the array elements cannot exceed 65535.",
        "",
        { "Separate the large array into multiple arrays." },
        {} } },
    { ERR_CODE_INVALID_QUANTITY,
      { ERR_CODE_INVALID_QUANTITY,
        ERR_TYPE_RESOURCE_PACK,
        "Invalid quantity '%s' of the resource '%s', it should be one of %s.",
        "",
        {},
        {} } },
    { ERR_CODE_DUPLICATE_QUANTITY,
      { ERR_CODE_DUPLICATE_QUANTITY,
        ERR_TYPE_RESOURCE_PACK,
        "Duplicated quantity '%s' of the plural resource '%s'.",
        "",
        { "Make sure the quantity of the plural resource is unique." },
        {} } },
    { ERR_CODE_QUANTITY_NO_OTHER,
      { ERR_CODE_QUANTITY_NO_OTHER,
        ERR_TYPE_RESOURCE_PACK,
        "The plural resource '%s' should contains 'other' quantity.",
        "",
        {},
        {} } },
    { ERR_CODE_INVALID_SYMBOL,
      { ERR_CODE_INVALID_SYMBOL,
        ERR_TYPE_RESOURCE_PACK,
        "Invalid value '%d' of the symbol resource '%s', it should be in the scope [0xF0000,0xFFFFF] or "
        "[0x100000,0x10FFFF].",
        "",
        {},
        {} } },
    { ERR_CODE_INVALID_RESOURCE_NAME,
      { ERR_CODE_INVALID_RESOURCE_NAME,
        ERR_TYPE_RESOURCE_PACK,
        "Invalid resource name '%s', it should be match the pattern [a-zA-Z0-9_].",
        "",
        { "Modify the name to match the pattern [a-zA-Z0-9_]." },
        {} } },
    { ERR_CODE_RESOURCE_DUPLICATE,
      { ERR_CODE_RESOURCE_DUPLICATE,
        ERR_TYPE_RESOURCE_PACK,
        "Resource '%s' conflict, first declared at '%s', but declare again at '%s'.",
        "",
        { "Make sure the resource name of the same type is unique." },
        {} } },
    { ERR_CODE_RESOURCE_ID_EXCEED,
      { ERR_CODE_RESOURCE_ID_EXCEED,
        ERR_TYPE_RESOURCE_PACK,
        "The resource id '%lu' exceed, greater than the max id '%lu'.",
        "",
        { "Delete useless resources and recompile.", "Specify a smaller start id." },
        {} } },
    { ERR_CODE_RESOURCE_ID_NOT_DEFINED,
      { ERR_CODE_RESOURCE_ID_NOT_DEFINED,
        ERR_TYPE_RESOURCE_PACK,
        "The id of resource '%s' of the '%s' type is not defined.",
        "",
        { "Delete useless resources and recompile." },
        {} } },
    { ERR_CODE_REF_NOT_DEFINED,
      { ERR_CODE_REF_NOT_DEFINED,
        ERR_TYPE_RESOURCE_PACK,
        "The resource reference '%s' is not defined.",
        "",
        { "Check whether this resource is defined anywhere." },
        {} } },
    { ERR_CODE_INVALID_RESOURCE_INDEX,
      { ERR_CODE_INVALID_RESOURCE_INDEX,
        ERR_TYPE_RESOURCE_PACK,
        "Failed to parse the resources.index file, %s.",
        "",
        { "Verify that the format of the resource.index file is correct." },
        {} } },

    // 11212xxx
    { ERR_CODE_PARSE_HAP_ERROR,
      { ERR_CODE_PARSE_HAP_ERROR, ERR_TYPE_RESOURCE_DUMP, "Failed to parse the hap, %s.", "", {}, {} } },
};

ErrorInfo GetError(const uint32_t &errCode)
{
    ErrorInfo error;
    if (ERRORS_MAP.count(errCode) == 0) {
        return error;
    }
    auto it = ERRORS_MAP.find(errCode);
    if (it != ERRORS_MAP.end()) {
        return it->second;
    }
    return error;
}

void PrintError(const uint32_t &errCode)
{
    PrintError(GetError(errCode));
}

void PrintError(const ErrorInfo &error)
{
    std::string errMsg;
    errMsg.append("Error Code: ").append(std::to_string(error.code_)).append("\n");
    errMsg.append("Error: ").append(error.description_).append("\n");
    errMsg.append("Error Message: ").append(error.cause_);
    if (!error.position_.empty()) {
        errMsg.append(" At file: ").append(error.position_);
    }
    errMsg.append("\n");
    if (!error.solutions_.empty()) {
        errMsg.append("* Try the following:").append("\n");
        for (const auto &solution : error.solutions_) { errMsg.append("  > ").append(solution).append("\n"); }
        if (!error.moreInfo_.cn.empty()) {
            errMsg.append("> More info: ").append(error.moreInfo_.cn).append("\n");
        }
    }
    std::cerr << errMsg;
}
} // namespace Restool
} // namespace Global
} // namespace OHOS
